/*++
"This software program is available to you under a choice of one of two 
licenses.  You may choose to be licensed under either the GNU General Public 
License (GPL) Version 2, June 1991, available at 
http://www.fsf.org/copyleft/gpl.html, or the BSD License, the text of
which follows:

Copyright (c) 1996-2005, Intel Corporation. All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer. 

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or 
other materials provided with the distribution. 

Neither the name of the Intel Corporation ("Intel") nor the names of its 
contributors may be used to endorse or promote products derived from this
software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
--*/
/* 
 * xllp_pm_micco.c
 *
 * xllp_pm_micco driver for Tavor PDK
 *
 */
 

#include "xllp_pm_micco.h"
//#include "ResourceLock.h"
#include "xllp_logmessage.h"

#define MICCO_PM_READ(reg, pval)	XllpPmMiccoRead(i2cRegs, ostRegs, reg, pval)
#define MICCO_PM_WRITE(reg, val)	XllpPmMiccoWrite(i2cRegs, ostRegs, reg, val)

/*
#define VBASE	1100
#define VSTEP	50
#define VMAX	2650
*/



#define VCC_APP_SRAM_BASE	725
#define VCC_APP_SRAM_STEP	25
#define VCC_APP_SRAM_MAX	1500

#define VCC_APP_BASE	725
#define VCC_APP_STEP	25
#define VCC_APP_MAX	1500

#define MICCO_I2C_WRITE_SLAVE_ADDRESS               0x68
#define MICCO_I2C_READ_SLAVE_ADDRESS                0x69

#define	micco_saddr 	(MICCO_I2C_WRITE_SLAVE_ADDRESS >> 1)

XLLP_STATUS_T XllpPmMiccoWrite(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs, 
			XLLP_UINT8_T reg, XLLP_UINT8_T val)
{
    XLLP_STATUS_T status;
	XLLP_UINT8_T buf[2];
#if 0
    if (RM_STATUS_SUCCESS != RM_AcquireLock(RM_RID_I2C, 0, RM_TIMEOUT_INFINITE))
    {
        xllp_LogMessage("XllpPmMiccoWrite - Failed getting I2C lock\r\n");
        return XLLP_STATUS_FAILURE;
    }
#endif    

	buf[0] = reg;
	buf[1] = val;
    status = XllpI2CWrite(i2cRegs, ostRegs, micco_saddr, buf, 2, 1); 	
//    RM_ReleaseLock(RM_RID_I2C, 0);

    return status;
}

XLLP_STATUS_T XllpPmMiccoRead(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs, 
			XLLP_UINT8_T reg, XLLP_UINT8_T *pval)
{
	XLLP_STATUS_T status;
#if 0
    if (RM_STATUS_SUCCESS != RM_AcquireLock(RM_RID_I2C, 0, RM_TIMEOUT_INFINITE))
    {
        xllp_LogMessage("XllpPmMiccoRead - Failed getting I2C lock\r\n");
        return XLLP_STATUS_FAILURE;
    }
#endif

	status = XllpI2CWrite(i2cRegs, ostRegs, micco_saddr, &reg, 1, 1); 
	if (status == XLLP_STATUS_SUCCESS) 
	{
		status = XllpI2CRead(i2cRegs, ostRegs, micco_saddr, pval, 1, 1);
	}

//    RM_ReleaseLock(RM_RID_I2C, 0);
    return status;
}

/* Make sure that Power I2C has been initialized before invoke this function */	
XLLP_STATUS_T XllpPmMiccoInit(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs)
{
//    RM_InitService();
	return XLLP_STATUS_SUCCESS;
}

XLLP_STATUS_T XllpPmMiccoSetVccSram(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs,
			 XLLP_UINT32_T mv)
{
	XLLP_STATUS_T status;
	XLLP_UINT8_T val;
#if 0
    if (RM_STATUS_SUCCESS != RM_AcquireLock(RM_RID_I2C, 0, RM_TIMEOUT_INFINITE))
    {
        xllp_LogMessage("XllpPmMiccoSetVccSram - Failed getting I2C lock\r\n");
        return XLLP_STATUS_FAILURE;
    }
#endif

	if (mv >= VCC_APP_SRAM_BASE && mv <= VCC_APP_SRAM_MAX)
	{

		status = MICCO_PM_READ(XLLP_MICCO_ADTV1, &val);
		if (status == XLLP_STATUS_SUCCESS)
		{
			val &= 0xE0;
			val |= ((mv - VCC_APP_SRAM_BASE)/VCC_APP_SRAM_STEP) & 0x1F;
			status = MICCO_PM_WRITE(XLLP_MICCO_ADTV1, val);
			if (status == XLLP_STATUS_SUCCESS)
			{
				val |= XLLP_MICCO_VCC1_SRAM_GO;
				val &= (~XLLP_MICCO_VCC1_SRAM_SEL);
				status = MICCO_PM_WRITE(XLLP_MICCO_VCC1, val);
			}
		}
	}
//    RM_ReleaseLock(RM_RID_I2C, 0);
	return status;

}

XLLP_STATUS_T XllpPmMiccoSetVccCore(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs,
			 XLLP_UINT32_T mv)
{
	XLLP_STATUS_T status;
	XLLP_UINT8_T val;

	if (mv >= VCC_APP_BASE && mv <= VCC_APP_MAX)
	{
		status = MICCO_PM_READ(XLLP_MICCO_ADTV1, &val);
		if (status == XLLP_STATUS_SUCCESS)
		{
			val &= 0xE0;
			val |= ((mv - VCC_APP_BASE)/VCC_APP_STEP) & 0x1F;
			status = MICCO_PM_WRITE(XLLP_MICCO_ADTV1, val);
			if (status == XLLP_STATUS_SUCCESS)
			{
				val = XLLP_MICCO_VCC1_APPS_GO;
				val &= (~XLLP_MICCO_VCC1_APPS_SEL);
				status = MICCO_PM_WRITE(XLLP_MICCO_VCC1, val);
			}
		}
	}
	// Introduce a fixed delay to ensure that the voltage change completes before we move the OP.
	// For the Navajo PMIC, this should be 40us.  This is a worst-case value, but safe.
	// Realize that the count loop here uses 3 ticks per us, when really it is 3.25.
	// This results in 120 tix instead of 130 tix.  I will therefore inflate the timeout to
	//   both compensate for this fact, and to also give us a buffer in case there is some 
	//	 varation from PMIC to PMIC.  Enlarge this timeout if you suspect Vmin issues.
	//
	//  This is done only here since, as of 9-14, we always change SRAM followed by APPS.
	//  If this assumption changes, then this wait will need to be placed after the supply
	//	  is adjusted, but before a frequency change is done.  Ideally, we would really only
	//	  do this in cases where we are going faster.  For now, we will always do it.  There are
	//	  several other optimizations that can also be applied, but for now we will not introduce
	//	  further risk by implementing them.
	//
	XllpOstDelayMicroSeconds(ostRegs, 60);

	return status;

}

XLLP_STATUS_T XllpPmMiccoGetVccSram(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs,
			 XLLP_UINT32_T *pmv)
{
	XLLP_STATUS_T status;
	XLLP_UINT8_T val;
#if 0
    if (RM_STATUS_SUCCESS != RM_AcquireLock(RM_RID_I2C, 0, RM_TIMEOUT_INFINITE))
    {
        xllp_LogMessage("XllpPmMiccoGetVccSram - Failed getting I2C lock\r\n");
        return XLLP_STATUS_FAILURE;
    }
#endif

	status = MICCO_PM_READ(XLLP_MICCO_SDTV2, &val);
	if (status == XLLP_STATUS_SUCCESS)
	{
		val = val & 0x1F;
		*pmv = (val) * VCC_APP_SRAM_STEP + VCC_APP_SRAM_BASE;
	}
//    RM_ReleaseLock(RM_RID_I2C, 0);
	return status;

}

XLLP_STATUS_T XllpPmMiccoGetVccCore(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs,
			 XLLP_UINT32_T *pmv)
{
	XLLP_STATUS_T status;
	XLLP_UINT8_T val;
#if 0
    if (RM_STATUS_SUCCESS != RM_AcquireLock(RM_RID_I2C, 0, RM_TIMEOUT_INFINITE))
    {
        xllp_LogMessage("XllpPmMiccoGetVccCore - Failed getting I2C lock\r\n");
        return XLLP_STATUS_FAILURE;
    }
 #endif
 
	//XLLP_MICCO_ADTV2
	status = MICCO_PM_READ(XLLP_MICCO_ADTV2, &val);

	if (status == XLLP_STATUS_SUCCESS)
	{
		val = val & 0x1F;
		*pmv = val * VCC_APP_STEP + VCC_APP_BASE;
	}
 //   RM_ReleaseLock(RM_RID_I2C, 0);
	return XLLP_STATUS_SUCCESS;
}


XLLP_STATUS_T XllpPmMiccoShutDown(XLLP_I2C_T *i2cRegs, XLLP_OST_T *ostRegs)
{
	XLLP_STATUS_T status=XLLP_STATUS_SUCCESS;
	XLLP_UINT8_T val;
#if 0
    if (RM_STATUS_SUCCESS != RM_AcquireLock(RM_RID_I2C, 0, RM_TIMEOUT_INFINITE))
    {
        xllp_LogMessage("XllpPmMiccoRead - Failed getting I2C lock\r\n");
        return XLLP_STATUS_FAILURE;
    }
#endif

	//disable and enable watchdog bit
	XllpPmMiccoWrite(i2cRegs,ostRegs, XLLP_MICCO_SYS_CTRL_A, XLLP_SYS_CTRL_A_WDT_ENABLE);
	XllpPmMiccoRead(i2cRegs, ostRegs, XLLP_MICCO_SYS_CTRL_A, &val);
	XllpPmMiccoWrite(i2cRegs, ostRegs, XLLP_MICCO_SYS_CTRL_A, XLLP_SYS_CTRL_A_RESET);
//    RM_ReleaseLock(RM_RID_I2C, 0);
    return status;
}


